import java.math.BigInteger;

/**
 * @author by zyl
 * @date 2020/3/28.
 */
public class ECCOperator {

    BigInteger a=new BigInteger("-3");
    BigInteger p;

    public ECCOperator(){
        p=new BigInteger("2");
        BigInteger two=p;
        p=p.pow(192);
        two=two.pow(64);
        p=p.subtract(two);
        p=p.subtract(new BigInteger("1"));
    }

    public BigInteger getP() {
        return p;
    }

    /**
     * 两解点相加
     * @param p1
     * @param p2
     * @return
     */
    public ECPoint add(ECPoint p1, ECPoint p2) {
        if (p1.isO()) return p2;
        if (p2.isO()) return p1;
        ECPoint p3 = new ECPoint();
        BigInteger lambda;
        if (p1.x.compareTo(p2.x) == 0) {
            if (p1.y.compareTo(p2.y) == 0) {
                lambda = new BigInteger("3").multiply(p1.x.pow(2)).add(a).multiply(new BigInteger("2").multiply(p1.y).modPow(new BigInteger("-1"), p)).mod(p);
                p3.x = lambda.pow(2).subtract(new BigInteger("2").multiply(p1.x)).mod(p);
                p3.y = lambda.multiply(p1.x.subtract(p3.x)).subtract(p1.y).mod(p);
                return p3;
            }
            if (p1.y.compareTo(p.subtract(p2.y)) == 0)
                return p3;
        }
        lambda = p2.y.subtract(p1.y).multiply(p2.x.subtract(p1.x).modPow(new BigInteger("-1"), p)).mod(p);
        p3.x = lambda.pow(2).subtract(p1.x).subtract(p2.x).mod(p);
        p3.y = lambda.multiply(p1.x.subtract(p3.x)).subtract(p1.y).mod(p);
        return p3;
    }

    /**
     * 倍乘
     * @param p
     * @param n
     * @return  np
     */
    public ECPoint multiply(ECPoint p, BigInteger n) {
        ECPoint q = add(p, new ECPoint());
        ECPoint r = new ECPoint();
        do {
            if (n.and(new BigInteger("1")).intValue() == 1)
                r = add(r, q);
            q = add(q, q);
            n = n.shiftRight(1);
        } while (n.intValue() != 0);
        return r;
    }

}